'\" t
.\"     Title: coap_resource
.\"    Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
.\"      Date: 12/27/2024
.\"    Manual: libcoap Manual
.\"    Source: coap_resource 4.2.0
.\"  Language: English
.\"
.TH "COAP_RESOURCE" "3" "12/27/2024" "coap_resource 4\&.2\&.0" "libcoap Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
coap_resource, coap_resource_init, coap_resource_unknown_init, coap_add_resource, coap_delete_resource, coap_delete_all_resources, coap_resource_set_mode \- Work with CoAP resources
.SH "SYNOPSIS"
.sp
\fB#include <coap2/coap\&.h>\fR
.sp
\fBcoap_resource_t *coap_resource_init(coap_str_const_t *\fR\fB\fIuri_path\fR\fR\fB, int \fR\fB\fIflags\fR\fR\fB);\fR
.sp
\fBcoap_resource_t *coap_resource_unknown_init(coap_method_handler_t \fR\fB\fIput_handler\fR\fR\fB);\fR
.sp
\fBvoid coap_add_resource(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, coap_resource_t *\fR\fB\fIresource\fR\fR\fB);\fR
.sp
\fBint coap_delete_resource(coap_context_t \fR\fB\fIcontext\fR\fR\fB, coap_resource_t \fR\fB\fIresource\fR\fR\fB);\fR
.sp
\fBvoid coap_delete_all_resources(coap_context_t *\fR\fB\fIcontext\fR\fR\fB);\fR
.sp
\fBvoid coap_resource_set_mode(coap_resource_t *\fR\fB\fIresource\fR\fR\fB, int \fR\fB\fImode\fR\fR\fB);\fR
.sp
Link with \fB\-lcoap\-2\fR, \fB\-lcoap\-2\-gnutls\fR, \fB\-lcoap\-2\-openssl\fR or \fB\-lcoap\-2\-tinydtls\fR depending on your (D)TLS library type\&.
.SH "DESCRIPTION"
.sp
CoAP Resources on a CoAP Server need to be created and updated etc\&. The URI in the request packet defines the resource to work with, with possibly the Query referring to a sub\-resource\&.
.sp
When resources are configured on the CoAP server, the URI to match against in the request packet is specified\&.
.sp
Callback Handlers are then added to the resource to handle the different request methods\&.
.sp
Adding Attributes allows textual information to be added to the resource which can then be reported back to any client doing a "GET \&.well\-known/core" request\&.
.sp
If an incoming packet request matches a resource\(cqs URI and Method, then the appropriate callback resource handler is invoked to process the packet which then should update a suitable response packet for sending back to the requester\&.
.sp
There is support for handling incoming packets where the URI is unknown\&. This could, for example, happen when a PUT request is trying to create a new resource\&. It is the responsibility of the unknown resource callback handler to either create a new resource for the URI or just manage things separately\&.
.sp
CoAP Observe (RFC 7641) is not supported for unknown resources, so a new resource with GET handler must be created by the unknown resource callback handle matching the URI which then can be Observable\&.
.sp
The \fBcoap_resource_init\fR() function returns a newly created \fIresource\fR of type \fIcoap_resource_t\fR * \&. \fIuri_path\fR specifies the uri string path to match against\&. \fIflags\fR is used to define whether the \fIresource\fR is of type Confirmable Message or Non\-Confirmable Message for any "observe" responses\&. See \fBcoap_observe\fR(3)\&. \fIflags\fR can be one of the following definitions or\(cqed together\&.
.TS
tab(:);
lt lt
lt lt
lt lt.
T{
.sp
\fBCOAP_RESOURCE_FLAGS_NOTIFY_NON\fR
T}:T{
.sp
Set the notification message type to non\-confirmable for any trigggered "observe" responses\&.
T}
T{
.sp
\fBCOAP_RESOURCE_FLAGS_NOTIFY_CON\fR
T}:T{
.sp
Set the notification message type to confirmable for any trigggered "observe" responses\&.
T}
T{
.sp
\fBCOAP_RESOURCE_FLAGS_RELEASE_URI\fR
T}:T{
.sp
Free off the coap_str_const_t for \fIuri_path\fR when the \fIresource\fR is deleted\&.
T}
.TE
.sp 1
.sp
\fBNOTE:\fR \fIuri_path\fR, if not 7 bit readable ASCII, binary bytes must be hex encoded according to the rules defined in RFC3968 Section 2\&.1\&.
.sp
The \fBcoap_resource_unknown_init\fR() returns a newly created \fIresource\fR of type \fIcoap_resource_t\fR *\&. \fIput_handler\fR is automatically added to the \fIresource\fR to handle PUT requests to resources that are unknown\&. Additional handlers can be added to this resource if required\&.
.sp
The \fBcoap_add_resource\fR() function registers the given \fIresource\fR with the \fIcontext\fR\&. The \fIresource\fR must have been created by \fBcoap_resource_init\fR(), or \fBcoap_resource_unknown_init\fR()\&. The storage allocated for the \fIresource\fR will be released by \fBcoap_delete_resource\fR()\&.
.sp
As the \fIuri_path\fR of the resource has to be unique across all of the resources associated with a \fIcontext\fR, \fBcoap_add_resource\fR() (or \fBcoap_add_resource_release\fR()) will delete any previous \fIresource\fR with the same \fIuri_path\fR before adding in the new \fIresource\fR\&.
.sp
The \fBcoap_delete_resource\fR() function deletes a \fIresource\fR identified by \fIresource\fR from \fIcontext\fR\&. The storage allocated for that \fIresource\fR is freed, along with any attrigutes associated with the \fIresource\fR\&.
.sp
The \fBcoap_delete_all_resources\fR() function deletes all resources from \fIcontext\fR and frees their storage\&.
.sp
The \fBcoap_resource_set_mode\fR() changes the notification message type of \fIresource\fR to the given \fImode\fR which must be one of COAP_RESOURCE_FLAGS_NOTIFY_NON or COAP_RESOURCE_FLAGS_NOTIFY_CON\&.
.SH "RETURN VALUES"
.sp
The \fBcoap_resource_init\fR() and \fBcoap_resource_unknown_init\fR() functions return a newly created resource or NULL if there is a malloc failure\&.
.sp
The \fBcoap_delete_resource\fR() function return 0 on failure (\fIresource\fR not found), 1 on success\&.
.SH "EXAMPLES"
.sp
\fBFixed Resources Set Up\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include <coap2/coap\&.h>

#define INDEX "This is an example server using libcoap\en"

void
hnd_get_index(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {
  unsigned char buf[3];

  response\->code = COAP_RESPONSE_CODE(205);

  coap_add_option(response,
                  COAP_OPTION_CONTENT_TYPE,
                  coap_encode_var_safe(buf, sizeof(buf),
                                       COAP_MEDIATYPE_TEXT_PLAIN),
                  buf);

  coap_add_option(response,
                  COAP_OPTION_MAXAGE,
                  coap_encode_var_safe(buf, sizeof(buf), 0x2ffff), buf);

  coap_add_data(response, strlen(INDEX), (const uint8_t *)INDEX);

}

void
hnd_delete_time(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  /* \&.\&. code \&.\&. */

}

void
hnd_get_time(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  /* \&.\&. code \&.\&. */

}

void
hnd_put_time(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  /* \&.\&. code \&.\&. */

}

static void
init_resources(coap_context_t *ctx) {

  coap_resource_t *r;

  /* Create a resource to return general information */
  r = coap_resource_init(NULL, 0);
  coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index);

  /* Document resource for \&.well\-known/core request */
  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
  coap_add_attr(r, coap_make_str_const("title"),
                coap_make_str_const("\e"General Info\e""), 0);

  coap_add_resource(ctx, r);

  /* Create a resource to return return or update time */
  r = coap_resource_init(coap_make_str_const("time"),
                         COAP_RESOURCE_FLAGS_NOTIFY_CON);
  coap_resource_set_get_observable(r, 1);
  coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time);
  coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time);
  coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time);

  /* Document resource for \&.well\-known/core request */
  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
  coap_add_attr(r, coap_make_str_const("title"),
                coap_make_str_const("\e"Internal Clock\e""), 0);
  coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\e"secs\e""),
                0);
  coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\e"clock\e""),
                0);

  coap_add_resource(ctx, r);

}
.fi
.if n \{\
.RE
.\}
.sp
\fBDynamic Resources Set Up\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include <coap2/coap\&.h>

/* Regular DELETE handler \- used by resources created by the
 * Unknown Resource PUT handler */

void
hnd_delete(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  /* \&.\&. code \&.\&. */

  /* Dynamic resource no longer required \- delete it */
  coap_delete_resource(ctx, resource);

}

/* Regular GET handler \- used by resources created by the
 * Unknown Resource PUT handler */

void
hnd_get(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  coap_str_const_t *get_uri_path;
  coap_string_t *get_query;
  coap_opt_iterator_t opt_iter;
  coap_opt_filter_t filter;
  coap_opt_t *option;
  int len;

  /*
   * request will be NULL if an Observe triggered request, so the uri_path,
   * if needed, must be abstracted from the resource\&.
   * The uri_path string is a const pointer
   */

  get_uri_path = coap_resource_get_uri_path(resource);
  get_query = query;

  /* \&.\&. code \&.\&. */

}

/* Regular PUT handler \- used by resources created by the
 * Unknown Resource PUT handler */

void
hnd_put(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  coap_string_t *put_uri_path;

  /* get the uri_path */
  put_uri_path = coap_get_uri_path(request);
  if (!put_uri_path) {
    response\->code = COAP_RESPONSE_CODE(404);
    return;
  }

  /* \&.\&. code \&.\&. */

  /* Need to do this as coap_get_uri_path() created it */
  coap_delete_string(put_uri_path);

}

/* Unknown Resource PUT handler */

void
hnd_unknown_put(coap_context_t *ctx, coap_resource_t *resource,
coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
coap_string_t *query, coap_pdu_t *response) {

  coap_resource_t *r;
  int len;
  coap_string_t *uri_path;

  /* get the uri_path \- which will get used by coap_resource_init() */
  uri_path = coap_get_uri_path(request);
  if (!uri_path) {
    response\->code = COAP_RESPONSE_CODE(404);
    return;
  }

  /* Check if new URI Path is valid */
  if (!check_url_fn (uri_path, request\->code)) {
    response\->code = COAP_RESPONSE_CODE(404);
    coap_delete_string(uri_path);
    return;
  }

  /*
   * Create a resource to handle the new URI
   * uri_path will get deleted when the resource is removed
   */
  r = coap_resource_init((coap_str_const_t*)uri_path,
        COAP_RESOURCE_FLAGS_RELEASE_URI | COAP_RESOURCE_FLAGS_NOTIFY_NON);
  coap_register_handler(r, COAP_REQUEST_PUT, hnd_put);
  coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete);
  /* We possibly want to Observe the GETs */
  coap_resource_set_get_observable(r, 1);
  coap_register_handler(r, COAP_REQUEST_GET, hnd_get);
  coap_add_resource(ctx, r);

  /* Do the PUT for this first call */
  hnd_put(ctx, r, session, request, token, query, response);

  return;

}

/* Initialize single Unknown Resource PUT handler */

static void
init_resources(coap_context_t *ctx) {

  coap_resource_t *r;

  /* Create a resource to handle PUTs to unknown URIs */
  r = coap_resource_unknown_init(hnd_unknown_put);
  /*
   * Additional handlers can be added \- for example
   *  coap_register_handler(r, COAP_REQUEST_POST, hnd_post_unknown);
   *  coap_register_handler(r, COAP_REQUEST_GET, hnd_get_unknown);
   *  coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_unknown);
   */
  coap_add_resource(ctx, r);

}
.fi
.if n \{\
.RE
.\}
.SH "SEE ALSO"
.sp
\fBcoap_attribute\fR(3), \fBcoap_context\fR(3), \fBcoap_observe\fR(3) and \fBcoap_handler\fR(3)
.SH "FURTHER INFORMATION"
.sp
See "RFC7252: The Constrained Application Protocol (CoAP)" for further information\&.
.SH "BUGS"
.sp
Please report bugs on the mailing list for libcoap: libcoap\-developers@lists\&.sourceforge\&.net
.SH "AUTHORS"
.sp
The libcoap project <libcoap\-developers@lists\&.sourceforge\&.net>
